package com.xu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.xu.base.enums.ResponseCodeEnum;
import com.xu.base.exception.ServiceException;
import com.xu.base.model.BaseSelectVo;
import com.xu.base.utils.AssertUtils;
import com.xu.base.utils.LocalDateUtils;
import com.xu.mybatis.model.PageInfo;
import com.xu.redis.service.SequenceService;
import com.xu.security.utils.SecurityUtils;
import com.xu.system.constant.Constants;
import com.xu.system.constant.FileCodeConstants;
import com.xu.system.enums.SequenceEnum;
import com.xu.system.model.convert.UserConvert;
import com.xu.system.model.entity.SysUser;
import com.xu.system.model.pojo.user.*;
import com.xu.system.service.IFileService;
import com.xu.system.service.IUserService;
import com.xu.system.service.db.ISysDeptService;
import com.xu.system.service.db.ISysUserDeptService;
import com.xu.system.service.db.ISysUserRoleService;
import com.xu.system.service.db.ISysUserService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户服务服务
 *
 * @Author: 许乾伟
 * @Date: 2024/12/17 14:28
 */
@Service
public class UserServiceImpl implements IUserService {

    @Resource
    ISysUserService sysUserService;
    @Resource
    ISysUserRoleService sysUserRoleService;
    @Resource
    ISysDeptService sysDeptService;
    @Resource
    ISysUserDeptService sysUserDeptService;
    @Resource
    IFileService fileService;
    @Resource
    UserConvert userConvert;
    @Resource
    SequenceService sequenceService;
    @Resource
    BCryptPasswordEncoder encoder;


    @Transactional(rollbackFor = ServiceException.class)
    @Override
    public boolean add(AddUserReq req) {
        verifyAccount(req.getAccount(), null);
        verifyWorkNumber(req.getWorkNumber(), null);
        SysUser sysUser = userConvert.toSysUser(req)
                .setPwd(encoder.encode(req.getPwd()))
                .setUserCode(sequenceService.generateCode(SequenceEnum.USER_CODE_RULE));
        boolean save = sysUserService.save(sysUser);
        AssertUtils.isFalse(save, ResponseCodeEnum.DATA_FAILED, "新增用户失败");
        //添加头像关联
        List<Long> fileIds = req.getHeadImageFileId() == null ? null : List.of(req.getHeadImageFileId());
        fileService.saveFileData(sysUser.getId(), FileCodeConstants.USER_HEAD_SOURCE_CODE, fileIds);
        //添加角色关联
        sysUserRoleService.saveUserRole(sysUser.getId(), req.getRoleIds());
        //添加部门关联
        sysUserDeptService.saveUserDept(sysUser.getId(), req.getDeptId());
        return true;
    }

    @Override
    public boolean edit(EditUserReq req) {
        verifyAdmin(req.getUserId(),"不能编辑超管信息");
        verifyAccount(req.getAccount(), req.getUserId());
        verifyWorkNumber(req.getWorkNumber(), req.getUserId());
        SysUser sysUser = sysUserService.getById(req.getUserId());
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户，无法编辑");
        sysUser.setUserName(req.getUserName())
                .setAccount(req.getAccount())
                .setWorkNumber(req.getWorkNumber())
                .setSex(req.getSex())
                .setBirthday(LocalDateUtils.yyyymmddToLocalDateTime(req.getBirthday()))
                .setPhone(req.getPhone())
                .setTellPhone(req.getTellPhone())
                .setJobTitle(req.getJobTitle())
                .setStatus(req.getStatus())
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        boolean update = sysUserService.updateById(sysUser);
        AssertUtils.isFalse(update, ResponseCodeEnum.DATA_FAILED, "编辑用户失败");
        //添加头像关联
        List<Long> fileIds = req.getHeadImageFileId() == null ? null : List.of(req.getHeadImageFileId());
        fileService.saveFileData(sysUser.getId(), FileCodeConstants.USER_HEAD_SOURCE_CODE, fileIds);
        //添加角色关联
        sysUserRoleService.saveUserRole(sysUser.getId(), req.getRoleIds());
        //添加部门关联
        sysUserDeptService.saveUserDept(sysUser.getId(), req.getDeptId());
        return false;
    }

    @Override
    public boolean del(Long userId) {
        verifyAdmin(userId, "不能删除超管信息");
        SysUser sysUser = sysUserService.getById(userId);
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户，无法删除");
        sysUser.setIsDelete(Boolean.TRUE)
                .setUpdateBy(SecurityUtils.getUserId())
                .setUpdateTime(LocalDateTime.now());
        return sysUserService.updateById(sysUser);
    }

    @Override
    public UserVo detail(Long userId) {
        SysUser sysUser = sysUserService.getById(userId);
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户");
        UserVo userVo = userConvert.toUserVo(sysUser);
        //获取角色
        userVo.setRoleIds(sysUserRoleService.getRoleIdsByUserId(userId));
        //获取部门
        userVo.setDeptId(sysUserDeptService.getDeptIdByUserId(userId));
        //获取头像
        userVo.setHeadImageFile(fileService.getOneFile(userId,FileCodeConstants.USER_HEAD_SOURCE_CODE));
        return userVo;
    }

    @Override
    public PageInfo<UserSimpleVo> pageInfo(QueryUserReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        List<SysUser> list = searchList(req);
        List<Long> userIds = list.stream().map(SysUser::getId).collect(Collectors.toList());
        PageInfo<SysUser> pageData = new PageInfo<>(list);
        return userConvert.toUserSimpleVoPage(pageData, new UserTranslateBo(deptMapByUserIds(userIds), fileService.getFileMapBySourceIds(userIds,FileCodeConstants.USER_HEAD_SOURCE_CODE)));
    }

    @Override
    public List<UserExcelVo> exportList(QueryUserReq req) {
        return null;
    }

    @Override
    public boolean resetPwd(Long userId) {
        SysUser sysUser = sysUserService.getById(userId);
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户");
        sysUser.setPwd(encoder.encode(Constants.DEFAULT_PWD));
        sysUser.setUpdateBy(SecurityUtils.getUserId());
        sysUser.setUpdateTime(LocalDateTime.now());;
        return sysUserService.updateById(sysUser);
    }

    @Override
    public boolean changePwd(ChangePwdReq req) {
        SysUser sysUser = sysUserService.getById(req.getUserId());
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户");
        sysUser.setPwd(encoder.encode(req.getPwd()));
        sysUser.setUpdateBy(SecurityUtils.getUserId());
        sysUser.setUpdateTime(LocalDateTime.now());
        return sysUserService.updateById(sysUser);
    }

    @Override
    public boolean changeStatus(Long userId, Boolean status) {
        AssertUtils.isNull(status, ResponseCodeEnum.PARAM_ERROR, "状态不能为空");
        SysUser sysUser = sysUserService.getById(userId);
        AssertUtils.isNull(sysUser, ResponseCodeEnum.DATA_FAILED, "未查询到用户");
        sysUser.setStatus(status);
        sysUser.setUpdateBy(SecurityUtils.getUserId());
        sysUser.setUpdateTime(LocalDateTime.now());
        return sysUserService.updateById(sysUser);
    }

    @Override
    public List<BaseSelectVo<Long, String>> allSelectList() {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq(SysUser.IS_DELETE, Boolean.FALSE);
        List<SysUser> list = sysUserService.list(wrapper);
        if (CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        return list.stream().map(item -> new BaseSelectVo<>(item.getId(), item.getUserName())).collect(Collectors.toList());
    }

    /**
     * 查询用户服务列表
     *
     * @param req
     * @return
     */
    private List<SysUser> searchList(QueryUserReq req) {
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.hasText(req.getUserName()), SysUser.USER_NAME, req.getUserName());
        wrapper.like(StringUtils.hasText(req.getAccount()), SysUser.ACCOUNT, req.getAccount());
        wrapper.like(StringUtils.hasText(req.getWorkNumber()), SysUser.WORK_NUMBER, req.getWorkNumber());
        wrapper.like(StringUtils.hasText(req.getJobTitle()), SysUser.JOB_TITLE, req.getJobTitle());
        wrapper.eq(req.getSex() != null, SysUser.SEX, req.getSex());
        wrapper.ge(StringUtils.hasText(req.getBirthdayStartTime()), SysUser.BIRTHDAY, req.getBirthdayStartTime());
        wrapper.le(StringUtils.hasText(req.getBirthdayEndTime()), SysUser.BIRTHDAY, req.getBirthdayEndTime());
        wrapper.like(StringUtils.hasText(req.getPhone()), SysUser.PHONE, req.getPhone());
        wrapper.like(StringUtils.hasText(req.getTellPhone()), SysUser.TELL_PHONE, req.getTellPhone());
        List<Long> userIds = new ArrayList<>();
        if (req.getRoleId() != null) {
            List<Long> ids = sysUserRoleService.getUserIdsByRoleId(req.getRoleId());
            if (CollectionUtils.isEmpty(ids)) {
                return new ArrayList<>();
            }
            userIds.addAll(ids);
        }
        if (req.getDeptId() != null) {
            List<Long> ids = sysUserDeptService.getUserIdsByDeptId(req.getDeptId());
            if (CollectionUtils.isEmpty(ids)) {
                return new ArrayList<>();
            }
            userIds.addAll(ids);
        }
        wrapper.in(CollectionUtils.isNotEmpty(userIds), SysUser.ID, userIds);
        wrapper.eq(req.getStatus() != null, SysUser.STATUS, req.getStatus());
        wrapper.eq(SysUser.IS_DELETE, Boolean.FALSE);
        wrapper.orderByDesc(SysUser.UPDATE_TIME);
        List<SysUser> list = sysUserService.list(wrapper);
        return list;
    }

    /**
     * 按用户id获取部门名称翻译集合
     * @param userIds
     * @return
     */
    private Map<Long,String> deptMapByUserIds(List<Long> userIds){
        List<Long> deptIds = sysUserDeptService.getDeptIdsByUserIds(userIds);
        if (CollectionUtils.isEmpty(deptIds)){
            return new HashMap<>();
        }
        return sysDeptService.getDeptNameMap(deptIds);
    }
    /**
     * 校验账号唯一性
     * @param account 账号
     * @param userId 用户id
     */
    private void verifyAccount(String account, Long userId) {
        long count = sysUserService.count(new QueryWrapper<SysUser>()
                .eq(SysUser.ACCOUNT, account)
                .ne(userId != null, SysUser.ID, userId)
                .eq(SysUser.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0, ResponseCodeEnum.DATA_FAILED, "用户账号已存在,请检查");
    }

    /**
     * 校验用户工号唯一性
     * @param workNumber 工号
     * @param userId 用户id
     */
    private void verifyWorkNumber(String workNumber, Long userId) {
        long count = sysUserService.count(new QueryWrapper<SysUser>()
                .ne(userId != null, SysUser.ID, userId)
                .eq(SysUser.WORK_NUMBER, workNumber)
                .eq(SysUser.IS_DELETE, Boolean.FALSE));
        AssertUtils.isTrue(count > 0, ResponseCodeEnum.DATA_FAILED, "工装名称已存在,请检查!");
    }

    /**
     * 超管账号校验
     * @param userId
     * @param msg
     */
    private void verifyAdmin(Long userId, String msg) {
        AssertUtils.isTrue(Constants.ADMIN_USER_ID.equals(userId), ResponseCodeEnum.HANDEL_FAILED, msg);
    }

}
